package com.ln.config;

import com.alibaba.fastjson.JSON;
import com.ln.Util.JwtUtil;
import com.ln.filter.MyFilter;
import com.ln.service.UserService;
import com.ln.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Ln
 * @version 终极版
 * @date 2023/1/3 11:07
 */
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private UserService userService;

    @Autowired
    private MyFilter filter;
    //指定账户和密码的来源
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //设置security认证的规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
    //设置security认证的规则
        http.formLogin()
//                .loginProcessingUrl("/login")
//                .loginPage("/login.html")
//                .successForwardUrl("/main")
                //登录成功进入处理的业务代码
                .successHandler(successHandler())
                //登录失败后进入处理的业务代码
                .failureHandler(failureHandler())
                .permitAll();

        //没有权限时跳转的路径
        http.exceptionHandling().accessDeniedHandler(deniedHandler());

        //禁用跨站伪造请求,不使用csrf过滤器。
        http.csrf().disable();

        //允许跨域
        http.cors();

        //设置其他路径需要认证后才能访问
        http.authorizeRequests().anyRequest().authenticated();
    }
    //权限不足
    private AccessDeniedHandler deniedHandler(){
        return (request, response, e) -> {
            response.setContentType("json/application;charset=utf-8");
            PrintWriter writer = response.getWriter();
            Result result=new Result(4003,"权限不足",null);
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);

            writer.flush();
            writer.close();
        };
    }

    //登录失败
    private AuthenticationFailureHandler failureHandler(){
        return (request, response, e)->{
            response.setContentType("json/application;charset=utf-8");
            PrintWriter writer = response.getWriter();
            Result result=new Result(5000,"账户或密码错误",null);
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);

            writer.flush();
            writer.close();
        };
    }
    //成功登录
    private AuthenticationSuccessHandler successHandler(){
        return (request,response,authentication)->{
            response.setContentType("json/application;charset=utf-8");
            PrintWriter writer = response.getWriter();
            User principal = (User) authentication.getPrincipal();
            String username = principal.getUsername();
            Collection<GrantedAuthority> authorities = principal.getAuthorities();

            List<String> collect = authorities.stream().map(item -> item.getAuthority()).collect(Collectors.toList());

            Map<String, Object> map = new HashMap<>();
            map.put("username",username);
            map.put("authorities",collect);
            String token = JwtUtil.createToken(map);

            Result result = new Result(2000, "登陆成功", token);
            String jsonString = JSON.toJSONString(result);
            writer.print(jsonString);

            writer.flush();
            writer.close();
        };
    }
}
